package com.wry.spring.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
import com.wry.spring.dao.User;
import com.wry.spring.extension.MyFactoryBean;
import com.wry.spring.service.impl.OrderServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.HashSet;
import java.util.TreeMap;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * <h1>  </h1>
 *
 * @author wry
 * @since 2025.04.03
 */
@RequestMapping("test")
@RestController
public class TestController {

    @SentinelResource("g1")
    @GetMapping("g1")
    public String get1() {

        return "ok";
    }

    @GetMapping("login")
    public String login() {
        return "ok";
    }

    @Resource
    private ApplicationContext applicationContext;

    @GetMapping("fac")
    public String fac() {
        MyFactoryBean bean = (MyFactoryBean) applicationContext.getBean("myFactoryBean");
        System.out.println(bean.getMsg());
        System.out.println();
        MyFactoryBean myFactoryBean = (MyFactoryBean) applicationContext.getBean("&myFactoryBean");
        System.out.println(myFactoryBean.getMsg());
        return "ok -> " + bean;
    }


//    @SentinelResource(value = "g1",
//            blockHandler = "ex1", blockHandlerClass = ExceptionUtils.class,
//            fallback = "fall1", fallbackClass = ExceptionUtils.class)
//    @GetMapping("g1")
//    public String sentinel() {
//
//        return "ok";
//    }

    @PostConstruct
    public void authorityRule() {
        AuthorityRule rule = new AuthorityRule();
        rule.setResource("info");
        rule.setStrategy(RuleConstant.AUTHORITY_WHITE);
        rule.setLimitApp("127.0.0.1,appB");
        AuthorityRuleManager.loadRules(Collections.singletonList(rule));
    }

    static class ExceptionUtils {

        public static String ex1() {
            return "异常时策略";
        }

        public static String fall1() {
            return "异常时策略";
        }
    }

    @Resource
    private OrderServiceImpl orderServiceImpl;

    @GetMapping("trans1")
    public String trans1() {
        orderServiceImpl.v3();
        return "ok";
    }


    static AtomicInteger[] progress = new AtomicInteger[10];
    static ExecutorService threadPool = Executors.newFixedThreadPool(10);
    static ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(1000000);
    public static void main(String[] args) throws InterruptedException {
        v2();
    }

    private static void v2() throws InterruptedException {
        for (int i = 0; i < 1000000; i++) {
            queue.put(i);
        }
        CountDownLatch latch = new CountDownLatch(1000000);
        for (int i = 0; i < 10; i++) {
            final int threadId = i;
            threadPool.submit(() -> {
                AtomicInteger atomicInteger = new AtomicInteger();
                while (true) {
                    Integer take = null;
                    try {
                        take = queue.take();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (take == null) {
                        break;
                    }
                    exec();
                    latch.countDown();
                    int num = atomicInteger.incrementAndGet();
                    System.out.println(threadId + "处理了 -> " + num);
                    System.out.println(threadId +" -> " + new BigDecimal(num).divide(new BigDecimal(100000),6, RoundingMode.HALF_UP).multiply(new BigDecimal(100)) + "%");
                }
            });
        }
        latch.await();
    }

    private static void v1() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            progress[i] = new AtomicInteger();
        }
        CountDownLatch latch = new CountDownLatch(1000000);
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            threadPool.submit(() -> {
                for (int j = 0; j < 100000; j++) {
                    exec();
                    int num = progress[finalI].incrementAndGet();
                    System.out.println(Thread.currentThread().getName() +" -> " + new BigDecimal(num).divide(new BigDecimal(100000),4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)) + "%");
                    latch.countDown();
                }
            });
        }
        latch.await();
    }

    private static void exec() {
        try { Thread.sleep(10L); } catch (InterruptedException e) { e.printStackTrace();}
    }
}
